/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @file  dwmac.c
 * @brief Semidrive. AUTOSAR 4.3.1 MCAL Eth plugins.
 */
#ifdef __cplusplus
extern "C" {
#endif

#include "cdefs.h"
#include "EthIf.h"
#include "EthBuff.h"
#include "EthDesc.h"
#include "Eth_Fault.h"
#include "dwmac_common.h"
#include "Mcal_Cache.h"
#include "Mcal_ArchOpt.h"

#define  MAX_FREAM_802_3_LEN  0x0600u
#define  ETHNET_II_802_3_OFFSET  0x08u

#if (MAX_ETH_RING_LENTH > 10)
#define  MAX_IRQ_RXTIMES_ETH  10u
#else
#define  MAX_IRQ_RXTIMES_ETH (MAX_ETH_RING_LENTH/2)
#endif

#define ETH_START_SEC_CODE_FAST
#include "Eth_MemMap.h"

/**
 * @name:
 * @Desc:
 * @param {uint8} CtrlIdx
 * @param {uint8*} fream
 * @param {uint16} freaml
 * @return {*}
 */
// Function to parse a received frame
static  void rx_fream_parser(uint8 CtrlIdx, uint8 *fream, uint16 freaml)
{
    // Variable to store the type of frame
    VAR(Eth_FrameType, AUTOMATIC) freamtype;
    // Variable to store whether the frame is a broadcast frame
    VAR(boolean, AUTOMATIC) isbroadcast = 1;
    // Variable to store the offset of the data in the frame
    VAR(uint16, AUTOMATIC) dataoffset = MAC_HEADER_LEN;

    // Check if the frame is a broadcast frame
    for (int i = 0; i < 6; i++) {
        if (fream[i] != (uint8)0xFF) {
            isbroadcast = 0;
            break;
        }
    }

    // Get the type of frame
    freamtype = fream[12];
    freamtype = freamtype << 8;
    freamtype |= fream[13];

    // Check if the frame is an 802.3 frame
    if (freamtype < MAX_FREAM_802_3_LEN) {
        // 802.3
        dataoffset += ETHNET_II_802_3_OFFSET;
        freamtype = fream[12 + ETHNET_II_802_3_OFFSET];
        freamtype = freamtype << 8;
        freamtype |= fream[13 + ETHNET_II_802_3_OFFSET];
    }

    // Indicate the received frame
    EthIf_RxIndication(CtrlIdx, freamtype, isbroadcast, fream + 6u, \
                       (Eth_DataType *)(fream + dataoffset), freaml - 18u);
}
/**
 * @name:
 * @Desc:
 * @param {uint8} CtrlIdx
 * @param {locked_desc_t *} f_desc
 * @param {boolean} report
 * @return {*}
 */
static enum rx_frame_status rx_fream_process(uint8 CtrlIdx, locked_desc_t *f_desc, boolean report)
{
    // Function to process received frames

    uint16 len;
    uint8 *freambuf;
    enum rx_frame_status ret = RX_BAD;

    // Check if the frame descriptor is valid
    if (f_desc->confirm & LOCKED_DESC_RX_MASK) {
#if (ETH_NO_CACHEABLE_NEEDED == STD_OFF)
        // Invalidate the cache range
        Mcal_InvalidateCache((uint32)f_desc->desc, \
                                    ROUNDUP(sizeof(struct dma_desc), CACHE_LINE));
#endif
        // Get the status of the received frame
        ret = dwmac_wrback_get_rx_status((struct dma_desc *)f_desc->desc);

        // Check if the descriptor is still in use
        if (ret == RX_DMA_PROCESS) {
            /* desc is still in use */
            return ret;
        }

        /*
            Whether recive correctly or not, desc has been consumed.
        */
        // Reset the confirm bit
        f_desc->confirm = 0;

        // Check if the frame was received correctly
        if (ret != RX_GOOD) {
            /*
                  Received the packet, but there is an exception,
                do not continue to transmit to the upper layer.
            */
            return ret;
        }

        // Get the address of the received frame
        freambuf = (uint8 *)EthBuffAddr(CtrlIdx, f_desc->buf_idx, TRUE);

        // Check if the frame needs to be reported
        if (report) {
            // Get the length of the received frame
            len = dwmac_wrback_get_rx_frame_len((struct dma_desc *)f_desc->desc);
#if (ETH_NO_CACHEABLE_NEEDED == STD_OFF)
            // Invalidate the cache range
            Mcal_InvalidateCache((uint32)freambuf, \
                                        ROUNDUP(len, CACHE_LINE));
#endif
            // Parse the received frame
            rx_fream_parser(CtrlIdx, freambuf, len);
        } else {
            /* Not reported, the flag needs to be verified next time, so restore the flag bit */
            f_desc->confirm = LOCKED_DESC_RX_DMA;
        }
    }

    // Return the status of the received frame
    return ret;
}
/**
 * @name:
 * @Desc:
 * @param {uint8} CtrlIdx
 * @param {locked_desc_t *} f_desc
 * @param {boolean} report
 * @return {*}
 */
static enum tx_frame_status tx_fream_process(uint8 CtrlIdx, locked_desc_t *f_desc, boolean report)
{
    enum tx_frame_status ret;
#if (ETH_NO_CACHEABLE_NEEDED == STD_OFF)
    // Invalidate the cache range of the descriptor
    Mcal_InvalidateCache((uint32)f_desc->desc, \
                                ROUNDUP(sizeof(struct dma_desc), CACHE_LINE));
#endif
    // Get the status of the descriptor
    ret = dwmac_wrback_get_tx_status((struct dma_desc *)f_desc->desc);

    /* dma own return */
    // If the status is TX_DMA_PROCESS, return it
    if (ret == TX_DMA_PROCESS ) {
        return ret;
    }

    // If report is true or the status is not TX_GOOD, call EthIf_TxConfirmation
    if (report || ret != TX_GOOD) {
        EthIf_TxConfirmation(CtrlIdx, f_desc->buf_idx, ret != TX_GOOD);

    }

    /* Whether sent correctly or not, desc has been consumed */
    // Set the confirm flag to 0
    f_desc->confirm = 0;
    return ret;
}

/**
 * @description:
 * @param {uint8} CtrlIdx
 * @param {uint8} Channel
 * @param {boolean} irq
 * @return {*}
 */
uint32 rx_indication(uint8 CtrlIdx, uint8 Channel)
{
    /* Probe for more packets */
    boolean pfmp = 0, need_press_desc;
    enum rx_frame_status ret_dma;
    uint32  max_cnt = MAX_IRQ_RXTIMES_ETH;
    locked_desc_t *fream, *fream_n;
    uint32  ret = (uint32)ETH_NOT_RECEIVED;

    do {

        if (max_cnt)
            max_cnt--;

        need_press_desc = 1;

        /* If not in poll mode,not sure there is a descriptor ok .
        so only touch it and not updata the ring cb */
        if (locked_desc_touch(CtrlIdx, Channel, &fream, TRUE)) {
            return ret;
        }

        if (fream->confirm & LOCKED_DESC_RX_MASK) {
            ret_dma = rx_fream_process(CtrlIdx, fream, !pfmp);

            /*  if irq mode there is dorp event, dorp count do not need soft dummy
             precess.in poll mode there is not exception.*/
            if ( RX_DMA_PROCESS == ret_dma) {
                return ret;
            }

            /* desc was onsumed ,TX_GOOD or other error */
            if (!pfmp) {
                /* only updata the ring cb,fream will not be modified */
                locked_desc_get(CtrlIdx, Channel, &fream, TRUE);
            }

            // Check if the DMA transfer was successful
            if (ret_dma == RX_GOOD) {
                // If there is no more data to be received, return ETH_RECEIVED
                if (!pfmp) {
                    ret = (uint32)ETH_RECEIVED;
                // If there is more data to be received, return ETH_RECEIVED_MORE_DATA_AVAILABLE
                } else {
                    need_press_desc = 0;
                    ret = (uint32)ETH_RECEIVED_MORE_DATA_AVAILABLE;
                }
            // If there is more data to be received, get the next descriptor
            } else if (pfmp) {
                locked_desc_get(CtrlIdx, Channel, &fream, TRUE);
            }
        }

        // do not need  free and realloc desc and membuf
        if (need_press_desc) {
            if (locked_desc_touch(CtrlIdx, Channel, &fream_n, TRUE)) {
                return ret;
            }
#if (ETH_NO_CACHEABLE_NEEDED == STD_OFF)
            // Invalidate the cache range for the DMA descriptor
            Mcal_InvalidateCache((uint32)fream_n->desc, \
                                        ROUNDUP(sizeof(struct dma_desc), CACHE_LINE));
#endif
            // Check if the RX timestamp status is valid
            if (dwmac_wrback_get_rx_timestamp_status((struct dma_desc *)fream->desc,
                    (struct dma_desc *)fream_n->desc)) {
                // Reinitialize the RX descriptor
                Eth_ReInitRxDesc(CtrlIdx, Channel, fream);
                // Get the locked descriptor
                locked_desc_get(CtrlIdx, Channel, &fream_n, TRUE);
                // Reinitialize the RX descriptor
                Eth_ReInitRxDesc(CtrlIdx, Channel, fream_n);
            } else {
                // Reinitialize the RX descriptor
                Eth_ReInitRxDesc(CtrlIdx, Channel, fream);
            }
        }
        // fix recv suspend
        if (dwmac_dma_rx_state_get(ETH_CFG_CTRL_REG_BASE(CtrlIdx), \
                                   Channel) == DMX_RX_SUSPND) {
            dwmac_rx_trigger(ETH_CFG_CTRL_REG_BASE(CtrlIdx), Channel);
        }
        if (0u == max_cnt) {
            /* max times */
            pfmp = 1;
            if (ret == (uint32)ETH_RECEIVED_MORE_DATA_AVAILABLE) {
                return ret;
            }
        }
    } while (1);
}

/**
 * @brief Handles receive operations for a specified Ethernet controller and channel.
 *
 * This static function is responsible for handling receive operations for the specified
 * Ethernet controller and channel. It first invokes the Ethernet fault injection receive
 * handler (if enabled) and then calls the `rx_indication` function to indicate that a
 * receive operation has occurred.
 *
 * @param CtrlIdx The index of the Ethernet controller for which the receive operation occurred.
 * @param Channel The channel on which the receive operation occurred.
 *
 * @note This function is static and should not be called directly from outside its scope.
 */
static  void rx_handle(uint8 CtrlIdx, uint8 Channel)
{
    EthFaultInj_Eth_Rx_Handler();
    rx_indication(CtrlIdx, Channel);
}
/**
 * @description:
 * @param {uint8} CtrlIdx
 * @param {uint8} Channel
 * @param {boolean} irq
 * @return {*}
 */
void tx_indication(uint8 CtrlIdx, uint8 Channel, boolean irq)
{
    enum tx_frame_status ret;
    locked_desc_t *fream;

    do {
        if (irq) {
            // If irq is true, get the descriptor from the locked_desc_get function
            if (locked_desc_get(CtrlIdx, Channel, &fream, FALSE)) {
                return;
            }
        } else {
            /* If not in poll mode,not sure there is a descriptor ok .
            so only touch it and not updata the ring cb */
            if (locked_desc_touch(CtrlIdx, Channel, &fream, FALSE)) {
                return;
            }
        }

        // If the descriptor is confirmed, process the frame
        if (fream->confirm & LOCKED_DESC_TX_MASK) {
            ret = tx_fream_process(CtrlIdx, fream, fream->confirm & \
                                   LOCKED_DESC_TX_CONFIRM);

            // If the descriptor has not been consumed, return
            if (ret == TX_DMA_PROCESS) {
                /* desc have not been consumed ,return */
                return;
            }

            /* desc was onsumed ,TX_GOOD or other error */
            if (!irq) {
                /* only updata the ring cb,fream will not be modified */
                locked_desc_get(CtrlIdx, Channel, &fream, FALSE);
            }
        }

        /* only when mem buf and dma desc are used need to release resources */
        EthBuffFree(CtrlIdx, fream->buf_idx, FALSE);
        free_dma_desc(CtrlIdx, Channel, FALSE);
        // the second times should polling
        irq = 0;
    } while (1);
}
/**
 * @name:
 * @Desc:
 * @param {uint8} CtrlIdx
 * @return {*}
 */
// This function handles the transmission of data
static void tx_handle(uint8 CtrlIdx, uint8 Channel)
{
    // Call the tx_indication function to indicate the transmission
    tx_indication(CtrlIdx, Channel, TRUE);
}
#if defined(ETH_RX_ERROR_RECOVER)
/**
 * @brief Reinitializes the DMA engine and related components of the specified Ethernet controller.
 *
 * This function performs a full reinitialization of the DMA engine and its associated components (MTL and MAC)
 * for a specified Ethernet controller. It first sets the controller mode to down to ensure that the network
 * interface is disabled during the reinitialization process. It then initiates a DMA reset and waits for it
 * to complete. Upon successful completion of the DMA reset, it initializes the DMA, MTL, and MAC components
 * according to the configuration parameters for the specified controller. Finally, it sets the controller
 * mode back to active to enable network communication.
 *
 * @param CtrlIdx The index or identifier of the Ethernet controller to reinitialize.
 *
 * @note This function assumes that the necessary configuration parameters (e.g., register base addresses,
 *       interrupt modes, MTU, and MAC layer speed) are accessible through the `ETH_CFG_CTRL_` macros and
 *       `ETH_CFG_CTRL_PARM_PTR` function, which are not defined in this function header. Additionally, it
 *       relies on the `Eth_SetControllerMode`, `dwmac_dma_reset`, `Eth_Ctrl_Init_DMA`, `Eth_Ctrl_Init_MTL`,
 *       and `Eth_Ctrl_Init_MAC` functions for controller mode setting, DMA reset, and component initialization,
 *       which are not defined in the provided code snippet.
 *
 * @return None. This function does not return a value. However, it relies on the `dwmac_dma_reset` function
 *         to detect and handle reset failures internally.
 */
void dwmac_dma_reinit(uint8 CtrlIdx)
{
  int reset_ret=0;
  Eth_SetControllerMode(CtrlIdx,ETH_MODE_DOWN);
  reset_ret  = dwmac_dma_reset(ETH_CFG_CTRL_REG_BASE(CtrlIdx));
  /* It is impossible to return a negative value */
  if(reset_ret >= 0){
    /* DMA Init */
    Eth_Ctrl_Init_DMA(CtrlIdx, ETH_CFG_CTRL_RX_INT_MODE(CtrlIdx),
                      ETH_CFG_CTRL_TX_INT_MODE(CtrlIdx));
    /* MTL Init */
    Eth_Ctrl_Init_MTL(CtrlIdx);
    /* MAC Init */
    Eth_Ctrl_Init_MAC(CtrlIdx, ETH_CFG_CTRL_PARM_PTR(CtrlIdx)->Mtu,
                     ETH_CFG_CTRL_PARM_PTR(CtrlIdx)->MacLayerSpeed);
    Eth_SetControllerMode(CtrlIdx,ETH_MODE_ACTIVE);
  }
}
#endif
/**
 * @name:
 * @Desc:
 * @param {uint8} CtrlIdx
 * @param {uint8} dma_ch
 * @param {uint8} rx_mtl_ch
 * @return {*}
 */
static void ctrl_handle(uint8 CtrlIdx, uint8 rx_mtl_ch)
{
    uint8 chan;
#if defined(ETH_RX_ERROR_RECOVER)
    uint32 cur_desc;
#endif
    uint32 ch_irq_en_sta;
    uint32 dma_status,rx_ctrl,intr_status;
    uint32 regbase = ETH_CFG_CTRL_REG_BASE(CtrlIdx);

    dma_status = readl(regbase + DMA_INT_STATUS);

    if (dma_status & DMA_INT_STATUS_MTL) {
        //MTL
        uint32 mtl_int_qx_status = readl(regbase + MTL_INTR_STATUS);
        uint8 rx_mtl_ch_num = 0;

        for (rx_mtl_ch_num = 0; rx_mtl_ch_num < ETH_MAX_DMA_CHANNEL; rx_mtl_ch_num++) {
            /* Check MTL Interrupt */
            if ((rx_mtl_ch & MTL_INTR_QXIS(rx_mtl_ch_num)) &&
                (mtl_int_qx_status & MTL_INTR_QXIS(rx_mtl_ch_num))) {
                /* read Queue x Interrupt status */
                uint32 status = readl(regbase + MTL_QUEUE_INT_CTRL(rx_mtl_ch_num));

                if (status & MTL_Q_INT_CTRL_RXOVFIS) {
                    /*  clear Interrupt */
                    writel(status | MTL_Q_INT_CTRL_RXOVFIS,
                           regbase + MTL_QUEUE_INT_CTRL(rx_mtl_ch_num));
                    dwmac_rx_trigger(regbase, rx_mtl_ch_num);
                    EthFaultInj_Eth_Mtl_Handler();
#if defined(ETH_RX_ERROR_RECOVER)
                    /* Rx only enable ch0 */
                    if(ETH_CTRL_FATAL_RETRY_NUM(CtrlIdx)){
                      cur_desc = readl(regbase + DMA_CH_CUR_RX_DESC(rx_mtl_ch_num));
                      /* SR bit still 0 and desc pointer not updated: unable to recover exception reinitialization */
                      if(ETH_CTRL_LAST_CUR_DESC(CtrlIdx) == cur_desc){
                        dwmac_dma_reinit(CtrlIdx);
                        ETH_CTRL_FATAL_RETRY_NUM(CtrlIdx) = 0;
                        ETH_CTRL_FATAL_REINIT_NUM(CtrlIdx) += 1;
                       }
                    }
#endif
                }
            }
        }
    }
#if !defined(ETH_DISABLE_IRQ_PULSE)
    chan = Mcal_Arch_clz(Mcal_Arch_rbitu32(dma_status & DMA_INT_STATUS_CHAN0_5));

    if (dma_status & (uint32)(((uint32)0x1) << chan)) {
        intr_status = readl(regbase + DMA_CH_STATUS(chan));
        /* clear the irq flags */
        writel((intr_status & 0x3fffc7u), regbase + DMA_CH_STATUS(chan));

        /* ABNORMAL interrupts */
        if ((intr_status & DMA_CH_STATUS_AIS)) {
            rx_ctrl = readl(regbase + DMA_CH_RX_CONTROL(chan));
            if(!( rx_ctrl& DMA_CH_RX_CTRL_SR)){
              ETH_CTRL_LAST_CUR_DESC(CtrlIdx) = readl(regbase + DMA_CH_CUR_RX_DESC(chan));
              writel(rx_ctrl | DMA_CH_RX_CTRL_SR ,regbase + DMA_CH_RX_CONTROL(chan));
              ETH_CTRL_FATAL_RETRY_NUM(CtrlIdx) += 1u;
              /*
                  When rolling back to 0, it will cause the recovery mechanism to fail,
                and choosing to sacrifice the accuracy of exception event counting
              */
              ETH_CTRL_FATAL_RETRY_NUM(CtrlIdx) |= 0x1u;
            }
        }

        /* TX/RX NORMAL interrupts */
        if ((intr_status & DMA_CH_STATUS_NIS)) {
            ch_irq_en_sta = readl(regbase + DMA_CH_INTR_ENA(chan));

            if (intr_status & (DMA_CH_STATUS_RI | DMA_CH_STATUS_RBU)) {
                if (ch_irq_en_sta & (DMA_CH_INTR_EN_RIE | DMA_CH_INTR_EN_RBUE)) {
                    rx_handle(CtrlIdx, chan);
                    /*
                        Any successful reception after reset the sr bit indicates that the
                        previous recovery was successful, and reset is not required for recovery.
                    */
                    ETH_CTRL_LAST_CUR_DESC(CtrlIdx) = 0xaaa55aa5u;
                }
            }

            if ((intr_status & DMA_CH_STATUS_TI)) {
                if ((ch_irq_en_sta & DMA_CH_INTR_EN_TIE)) {
                    tx_handle(CtrlIdx, chan);
                }
            }
        }
        // fix recv suspend
        if (dwmac_dma_rx_state_get(ETH_CFG_CTRL_REG_BASE(CtrlIdx), \
                                   chan) == DMX_RX_SUSPND) {
            rx_handle(CtrlIdx, chan);
        }
    }
#else
    for(chan =0;chan < ETH_MAX_DMA_CHANNEL ;chan++){
        // read the interrupt status register
        intr_status = readl(regbase + DMA_CH_STATUS(chan));
        // check if the PERCH bit is set
        if(intr_status & DMA_CH_STATUS_PERCH){
          /* clear the irq flags */
          // write the cleared interrupt status to the interrupt status register
          writel((intr_status & 0x3fffc7u), regbase + DMA_CH_STATUS(chan));

          /* ABNORMAL interrupts */
          // check if the AIS bit is set
          if ((intr_status & DMA_CH_STATUS_AIS)) {
            // read the receive control register
            rx_ctrl = readl(regbase + DMA_CH_RX_CONTROL(chan));
            // check if the SR bit is not set
            if(!( rx_ctrl& DMA_CH_RX_CTRL_SR)){
              // write the current receive descriptor to the last/current descriptor register
              ETH_CTRL_LAST_CUR_DESC(CtrlIdx) = readl(regbase + DMA_CH_CUR_RX_DESC(chan));
              // set the SR bit in the receive control register
              writel(rx_ctrl | DMA_CH_RX_CTRL_SR ,regbase + DMA_CH_RX_CONTROL(chan));
              // increment the fatal retry number
              ETH_CTRL_FATAL_RETRY_NUM(CtrlIdx) += 1u;
              /*
                  When rolling back to 0, it will cause the recovery mechanism to fail,
                and choosing to sacrifice the accuracy of exception event counting
              */
              // set the first bit of the fatal retry number
              ETH_CTRL_FATAL_RETRY_NUM(CtrlIdx) |= 0x1u;
            }
          }

            /* TX/RX NORMAL interrupts */
            // read the interrupt enable register
            ch_irq_en_sta = readl(regbase + DMA_CH_INTR_ENA(chan));

            // check if the RI or RBU bits are set
            if (intr_status & (DMA_CH_STATUS_RI | DMA_CH_STATUS_RBU)) {
                // check if the RIE or RBUE bits are set
                if (ch_irq_en_sta & (DMA_CH_INTR_EN_RIE | DMA_CH_INTR_EN_RBUE)) {
                    // handle the receive interrupt
                    rx_handle(CtrlIdx, chan);
                    /*
                        Any successful reception after reset the sr bit indicates that the
                        previous recovery was successful, and reset is not required for recovery.
                    */
                    // write the last/current descriptor to the last/current descriptor register
                    ETH_CTRL_LAST_CUR_DESC(CtrlIdx) = 0xaaa55aa5u;
                }
            }

            // check if the TI bit is set
            if ((intr_status & DMA_CH_STATUS_TI)) {
                // check if the TIE bit is set
                if ((ch_irq_en_sta & DMA_CH_INTR_EN_TIE)) {
                    // handle the transmit interrupt
                    tx_handle(CtrlIdx, chan);
                }
            }
        }
        // fix recv suspend
        // check if the receive state is suspended
        if (dwmac_dma_rx_state_get(ETH_CFG_CTRL_REG_BASE(CtrlIdx), \
                                   chan) == DMX_RX_SUSPND) {
            // handle the receive interrupt
            rx_handle(CtrlIdx, chan);
        }
    }
#endif /** #if !defined(ETH_DISABLE_IRQ_PULSE) */
    /* Error Inject Point */
    EthFaultInj_Eth_ctrl_handle_Mac();

    if (DMA_INT_STATUS_MAC & dma_status) {
        mac_irq_handler(CtrlIdx,regbase);
    }
}

/**
 * @brief Interrupt Service Routine (ISR) for Ethernet controller 0.
 *
 * This ISR is invoked when an interrupt is generated by the Ethernet controller
 * with index 0. It first calls the Ethernet fault injection IRQ entry handler
 * (if enabled), handles control operations specific to this controller and channel,
 * and then calls the Ethernet fault injection IRQ exit handler (if enabled).
 *
 * @note This ISR is automatically registered using the ISR() macro and should not
 *       be called directly from application code.
 */
ISR(eth0_handle)
{
    // Call the function to handle the Ethernet fault injection interrupt entry
    EthFaultInj_Eth_Irq_Entry();
    // Call the function to handle the control
#if (ETH_DIRECT_FORWARD_ENABLE == STD_ON)
    ctrl_handle(ETH1, (BIT(RX_CHANNEL_IDX(ETH1, ETH_DIRECT_FORWARD_RX_CHANNEL)) |
                       BIT(0)));
#else
    ctrl_handle(ETH1, BIT(0));
#endif /* ETH_DIRECT_FORWARD_ENABLE  */

    // Call the function to handle the Ethernet fault injection interrupt exit
    EthFaultInj_Eth_Irq_Exit();
}
#if (ETH_MAXCTRLS_SUPPORTED == 2U)
/**
 * @brief Interrupt Service Routine (ISR) for Ethernet controller 1.
 *
 * This ISR is automatically invoked by the interrupt controller when an interrupt
 * is generated by the Ethernet controller with index 1. It first calls the Ethernet
 * fault injection IRQ entry handler (if enabled), then handles control operations
 * specific to this controller and channel 0, and finally calls the Ethernet fault
 * injection IRQ exit handler (if enabled).
 *
 * @note This ISR is automatically registered using the ISR() macro and should not
 *       be called directly from application code.
 */
ISR(eth1_handle)
{
    // Call the function to handle the Ethernet fault injection interrupt entry
    EthFaultInj_Eth_Irq_Entry();
    // Call the function to handle the control
#if (ETH_DIRECT_FORWARD_ENABLE == STD_ON)
    ctrl_handle(ETH2, (BIT(RX_CHANNEL_IDX(ETH2, ETH_DIRECT_FORWARD_RX_CHANNEL)) |
                       BIT(0)));
#else
    ctrl_handle(ETH2, BIT(0));
#endif /* ETH_DIRECT_FORWARD_ENABLE  */

    // Call the function to handle the Ethernet fault injection interrupt exit
    EthFaultInj_Eth_Irq_Exit();

}
#endif

#define ETH_STOP_SEC_CODE_FAST
#include "Eth_MemMap.h"

#ifdef __cplusplus
}
#endif
